import json,copy
from PySide6.QtCore import QDateTime

from Devices.Chiot.BsDevs.ComDev.ComDev import ComDev

CLIENT_CLOUD = "PC"
CLIENT_TOOL = "NetworkTest"

class ComDevParser(object):
    def PackBase(obj, msgvalue, msgName):
        msgvalue["commandId"] = "asfasdfasf"
        msgvalue["traceId"] = "asfasdfasf"

        data = {}
        data["msgname"] = msgName
        data["msgvalue"] = msgvalue

        obj["data"] = data
        obj["client"] = CLIENT_CLOUD
        obj["time"] = QDateTime.currentMSecsSinceEpoch()
        return obj

    def PackAttr(msgvalue, attrName, propertyName, propertyValue):
        attr = {}
        properties = {}
        if attrName in msgvalue:
            attr = msgvalue[attrName]
            properties = attr["properties"]

        properties[propertyName] = propertyValue
        attr["properties"] = properties
        msgvalue[attrName] = attr

    def PackCustomCmd(paramName, paramValue):
        data = {}
        data["client"] = "NetworkTest"
        data["time"] = QDateTime.currentSecsSinceEpoch()
        data["cmd"] = "custom"
        data["data"] = paramName
        if paramValue != None:
            data["data"] += "=" + str(paramValue)
        return json.dumps(data, separators=(',', ':'))

    def PackSetAttr(attrName, propertyName, propertyValue):
        msgvalue = {}
        ComDevParser.PackAttr(msgvalue, attrName, propertyName, propertyValue)

        obj = {}
        jsonDoc = ComDevParser.PackBase(obj, msgvalue, "setAttributes")
        return json.dumps(jsonDoc, separators=(',', ':'))

    def PackSetConfig(attrName, propertyName, propertyValue):
        pass

    def PackSetTimer(timer):
        timer_json = {}
        timer_json["id"] = timer.id
        timer_json["enable"] = 1 if timer.enable else 0

        services = []
        for i in range(len(timer.services)):
            service = {}
            service["serviceId"] = timer.services[i].serviceId
            service["para"] = timer.services[i].para
            service["paraValue"] = timer.services[i].paraValue
            services.append(service)
        timer_json["services"] = services
        timer_json["start"] = timer.start
        timer_json["end"] = timer.end
        timer_json["week"] = timer.week

        timers_json = []
        timers_json.append(timer_json)

        msgvalue = {}
        msgvalue["timer"] = timers_json
        obj = {}
        jsonDoc = ComDevParser.PackBase(obj, msgvalue, "setConfig")
        return json.dumps(jsonDoc, separators=(',', ':'))

    def PackSetDelay(delay):
        delay_json = {}
        delay_json["id"] = delay.id
        delay_json["enable"] = 1 if delay.enable else 0

        services = []
        for i in range(len(delay.services)):
            service = {}
            service["serviceId"] = delay.services[i].serviceId
            service["para"] = delay.services[i].para
            service["paraValue"] = int(delay.services[i].paraValue)
            services.append(service)

        delay_json["services"] = services
        delay_json["start"] = int(delay.start)
        delay_json["end"] = int(delay.end)

        msgvalue = {}
        msgvalue["delay"] = delay_json
        obj = {}
        jsonDoc = ComDevParser.PackBase(obj, msgvalue, "setConfig")
        return json.dumps(jsonDoc, separators=(',', ':'))

    def PackUpgrade(upgradePackageId, downloadUrl, mac, newVersion, md5, size):
        msgvalue = {}
        msgvalue["size"] = size
        msgvalue["downloadUrl"] = downloadUrl
        msgvalue["otaReportFreq"] = "5"
        msgvalue["update"] = True
        msgvalue["upgradePackageId"] = upgradePackageId
        msgvalue["upgradePackageUuid"] = upgradePackageId
        msgvalue["mac"] = mac
        msgvalue["newVersion"] = newVersion
        msgvalue["md5"] = md5

        obj = {}
        jsonDoc = ComDevParser.PackBase(obj, msgvalue, "update")
        return json.dumps(jsonDoc, separators=(',', ':'))

    def PackSetTimezone(timezone):
        msgvalue = {}
        msgvalue["timezone"] = str(timezone)

        obj = {}
        jsonDoc = ComDevParser.PackBase(obj, msgvalue, "heartbeatResponse")
        return json.dumps(jsonDoc, separators=(',', ':'))

    def PackUnbind(mac):
        msgvalue = {}
        msgvalue["isClean"] = 0
        msgvalue["mac"] = mac

        obj = {}
        jsonDoc = ComDevParser.PackBase(obj, msgvalue, "unbinding")
        return json.dumps(jsonDoc, separators=(',', ':'))

    def PackGetFullStatus():
        obj = {}
        obj["client"] = CLIENT_TOOL
        obj["cmd"] = "getFullStatus"
        obj["time"] =  QDateTime.currentMSecsSinceEpoch()

        return json.dumps(obj, separators=(',', ':'))
    
    def PackNeedFullStatus(macStr):
        msgvalue = {}
        msgvalue["needFullStatus"] = []
        msgvalue["needFullStatus"].append(macStr)

        obj = {}
        jsonDoc = ComDevParser.PackBase(obj, msgvalue, "needFullHeartbeat")
        ret = json.dumps(jsonDoc, separators=(',', ':'))
        return ret  
    
    def PackGetVerify():
        obj = {}
        obj["client"] = CLIENT_TOOL
        obj["cmd"] = "deviceVerify"
        obj["time"] =  QDateTime.currentMSecsSinceEpoch()

        return json.dumps(obj, separators=(',', ':'))
    
    def PackGetVerifyRsp(dataStr):
        obj = {}
        obj["client"] = CLIENT_TOOL
        obj["cmd"] = "deviceVerify3"
        obj["verify"] = dataStr
        obj["time"] =  QDateTime.currentMSecsSinceEpoch()

        return json.dumps(obj, separators=(',', ':'))

    def PackSetWiFi(ssid, pwd):
        obj = {}
        obj["client"] = CLIENT_TOOL
        obj["cmd"] = "setWiFi"
        obj["ssid"] = ssid
        obj["pwd"] = pwd

        return json.dumps(obj, separators=(',', ':'))
    
    def PackSetCloudType(cloudType):
        obj = {}
        obj["client"] = CLIENT_TOOL
        obj["cmd"] = "setChcloudType"
        obj["serverType"] = int(cloudType)

        return json.dumps(obj, separators=(',', ':'))

    def __GetTheProperty(obj, propertyName):
        """
        {
            "command":1,
        }
        __GetTheProperty(obj, "command")
        """
        if not propertyName in obj:
            return (False, None)

        value = obj[propertyName]
        return (True, value)

    def __GetAttrProperty(obj, attrName, propertyName):
        """
        {
            "switch": {
                "properties": {
                    "on": 1
                }
            }
        }
        __GetAttrProperty(obj, "switch", "on") 
        """
        if not attrName in obj:
            return (False, None)

        attr = obj[attrName]
        if not "properties" in attr:
            return (False, None)

        oneProperty = attr["properties"]
        if not propertyName in oneProperty:
            return (False, None)

        value = oneProperty[propertyName]
        return (True, value)

    def GetStrProperty(obj, *args):
        if (1 == len(args)):
            ret, strVal = ComDevParser.__GetTheProperty(obj, args[0])
        elif (len(args) > 1):
            ret, strVal = ComDevParser.__GetAttrProperty(obj, args[0], args[1])
        
        if ret:
            return (True, str(strVal))
        else:
            return (False, "")

    def GetIntProperty(obj, *args):
        if (1 == len(args)):
            ret, intVal = ComDevParser.__GetTheProperty(obj, args[0])
        elif (len(args) > 1):
            ret, intVal = ComDevParser.__GetAttrProperty(obj, args[0], args[1])
        
        if ret:
            return (True, int(intVal))
        else:
            return (False, 0)

    def GetServices(obj, attrName):
        """
        {
            "serviceId": "switch1",
            "para": "on",
            "paraValue": 1
        },
        GetServices()
        """
        if not attrName in obj:
            return (False, None)

        services = obj[attrName]
        serviceList = []
        for i in range(len(services)):
            if services[i] is None:
                return (False, None)
            service = services[i]
            if (not "serviceId" in service) or (not "para" in service) or (not "paraValue" in service):
                return (False, None)

            sp = ComDev.ServiceParams(service["serviceId"], service["para"], int(service["paraValue"]))
            serviceList.append(sp)

        return (True, serviceList)

    def GetTimers(obj, attrName, timerList, timerObj):
        if not attrName in obj:
            timerList.clear()
            return False

        timerList.clear()

        timersJson = obj[attrName]
        for timerJson in timersJson:
            if None == timerJson:
                return False
            
            if (not "id" in timerJson) or (not "enable" in timerJson) or (not "start" in timerJson) or (not "end" in timerJson) or (not "services" in timerJson) or (not "week" in timerJson):
                return False

            ret, serviceList = ComDevParser.GetServices(timerJson, "services")
            if not ret:
                return False

            timerObj.id = timerJson["id"]
            timerObj.enable = bool(timerJson["enable"])
            timerObj.start = timerJson["start"]
            timerObj.end = timerJson["end"]
            timerObj.services = serviceList
            timerObj.week = int(timerJson["week"])
            
            # timerObj = ComDev.Timer(service["id"], bool(service["enable"]), service["start"], service["end"], serviceList, int(service["week"]))
            timerList.append(copy.deepcopy(timerObj))
        return True

    def GetDelay(obj, attrName, delay):
        if not attrName in obj:
            delay.Reset()
            return False

        delay.Reset()
        if isinstance(obj[attrName], list):
            print("delay is a list.")
            if len(obj[attrName]) > 0:
                delayJson = obj[attrName][0]
            else:
                delay.enable = False
                delay.end = 0
                return True
        else:
            delayJson = obj[attrName]

        if (not "id" in delayJson) or (not "enable" in delayJson) or (not "start" in delayJson) or (not "end" in delayJson) or (not "services" in delayJson):
            delay.enable = False
            delay.end = 0
            return False

        delay.id = delayJson["id"]
        delay.enable = bool(delayJson["enable"])
        delay.end = delayJson["end"]

        ret, serviceList = ComDevParser.GetServices(delayJson, "services")
        if not ret:
            return False
        delay.services = serviceList

    def ParseMsg(data):
        doc = json.loads(data)
        if doc is None:
            return (False, None, None)

        if not "data" in doc:
            return (False, None, None)

        dataObj = doc["data"]
        if not "msgname" in dataObj:
            return (False, None, None)

        msgName = dataObj["msgname"]

        if not "msgvalue" in dataObj:
            return (False, None, None)

        msgValue = dataObj["msgvalue"]

        return (True, msgName, msgValue)

    def ParseFullStatus(msgValue, fullStatus):
        ret, strValue = ComDevParser.GetStrProperty(msgValue, "mac")
        if ret:
            fullStatus.mac = strValue

        ret, strValue = ComDevParser.GetStrProperty(msgValue, "firmwareVersion")
        if ret:
            fullStatus.firmwareVersion = strValue

        ret, strValue = ComDevParser.GetStrProperty(msgValue, "hardwareVersion")
        if ret:
            fullStatus.hardwareVersion = strValue

        ret, strValue = ComDevParser.GetStrProperty(msgValue, "protocol")
        if ret:
            fullStatus.protocol = strValue

        ret, strValue = ComDevParser.GetStrProperty(msgValue, "modelId")
        if ret:
            fullStatus.modelId = strValue

        ret, value = ComDevParser.GetIntProperty(msgValue, "serverType")
        if ret:
            fullStatus.serverType = value

        ret, value = ComDevParser.GetIntProperty(msgValue, "heartbeatFreq")
        if ret:
            fullStatus.heartbeatFreq = value

        ret, value = ComDevParser.GetIntProperty(msgValue, "nowTimestamp")
        if ret:
            fullStatus.nowTimestamp = value

        ret, strValue = ComDevParser.GetStrProperty(msgValue, "chipId")
        if ret:
            fullStatus.chipType = strValue

        ret, strValue = ComDevParser.GetStrProperty(msgValue, "serialNum")
        if ret:
            fullStatus.serialNum = strValue
        
        ret, strValue = ComDevParser.GetStrProperty(msgValue, "buildTime")
        if ret:
            fullStatus.buildTime = strValue

        ret, value = ComDevParser.GetIntProperty(msgValue, "mqttStatus")
        if ret:
            fullStatus.mqttStatus = value

        ret, value = ComDevParser.GetIntProperty(msgValue, "bindStatus")
        if ret:
            fullStatus.bindStatus = value

        if not "stateValue" in msgValue:
            return True
        stateValue = msgValue["stateValue"]

        ret, strValue = ComDevParser.GetStrProperty(stateValue, "timezone", "timezone")
        if ret:
            fullStatus.timezone = strValue

        ret, value = ComDevParser.GetStrProperty(stateValue, "netInfo", "RSSI")
        if ret:
            fullStatus.wifiRssi = value

        ret, strValue = ComDevParser.GetStrProperty(stateValue, "netInfo", "BSSID")
        if ret:
            fullStatus.wifiBssid = strValue

        ret, strValue = ComDevParser.GetStrProperty(stateValue, "netInfo", "SSID")
        if ret:
            fullStatus.wifiSsid = strValue

        return True

    def ParseOtaResult(msgValue, OtaResult):
        if not "stateValue" in msgValue:
            return False

        stateValue = msgValue["stateValue"]
        ret, strValue = ComDevParser.GetStrProperty(stateValue, "result")
        if ret:
            OtaResult.startTime = int(strValue)

        ret, strValue = ComDevParser.GetStrProperty(stateValue, "failReason")
        if ret:
            OtaResult.failReason = strValue
        return True

    def ParseOtaProcess(msgValue, otaProcess):
        if not "stateValue" in msgValue:
            return False
        stateValue = msgValue["stateValue"]

        ret, strValue = ComDevParser.GetStrProperty(stateValue, "startTime")
        if ret:
            otaProcess.startTime = strValue

        ret, strValue = ComDevParser.GetStrProperty(stateValue, "totalTime")
        if ret:
            otaProcess.totalTime = strValue

        ret, strValue = ComDevParser.GetStrProperty(stateValue, "progress")
        if ret:
            otaProcess.progress = strValue

        ret, strValue = ComDevParser.GetStrProperty(stateValue, "frequency")
        if ret:
            otaProcess.frequency = strValue

        ret, strValue = ComDevParser.GetStrProperty(stateValue, "process")
        if ret:
            otaProcess.process = strValue

        return True

    def ParseCmdCustom(msgValue, fullStatus):            
        if not "stateValue" in msgValue:
            return False
        stateValue = msgValue["stateValue"]
        # TODO 添加自定义数据处理 

        return True
